package main

import (
	"fmt"
	"github.com/hoisie/redis"
	"encoding/json"
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
	"strconv"
	"strings"
	"errors"
	"gopkg.in/yaml.v2"
	"io/ioutil"
)

//{"advertiser": [], "areaid": [1156000000], "cid": [], 
//"sspid": [381], "industry": [2], "pid": [], "business_id": []}
type blockRule struct {
	Advertiser []int `json:"advertiser"` //'select advertiser_id from blockrule_advertiser where blockrule_id = %d' % id
	Areaid []int `json:"areaid"` //'select area_id from blockrule_area where blockrule_id = %d' % id
	Cid []int `json:"cid"` //[]
	Sspid []int `json:"sspid"` //'select media_id from blockrule_media where blockrule_id = %d' % id
	Industry []int `json:"industry"` // 'select industry_id from blockrule_industry where blockrule_id = %d' % id
	Pid []int `json:"pid"` //[]
	BusinessId []int `json:"business_id"` //[]
}

//"{\"category\": 12, \"bundle_name\": \"\", \"terminal_id\": 1, \"product_id\": 120}"
type businessLine struct {
	//'select id, app_pkg_name, category_id, platform_id, product_id from biz where delete_flag = 0 and audit_status = 1'
	Category int `json:"category"` 
	BundleName string `json:"bundle_name"`
	TerminalId int `json:"terminal_id"` 
	ProductId int `json:"product_id"`
}

//adzone_material_type
//'select ad_type from adzone_ad_types where adzone_id = %d' % adzone_id
//{0:"image/jpeg", 1:"image/png", 3:"application/x-shockwave-flash", 4:"video/x-flv", 5:"video/mp4", 6:"image/gif", 7:"application/letv-vpaid"}

//adzone
//"{\"media_id\": 319, \"height\": 300, \"width\": 620, \"business_line\": 2170, 
//\"roll_type\": 2, \"publisher_id\": 3, \"click\": [], \"exposure\": []}"
type adzone struct {
	//select media_id, biz_id, roll_type, width, height from adzone where id = ?
	MediaId int `json:"media_id"`
	BusinessLine int `json:"business_line"`
	RollType int `json:"roll_type"`
	Width int `json:"width"`
	Height int `json:"height"`
	PublisherId int `json:"publisher_id"` //select b.publisher_id from adzone a,media b where a.media_id = b.id
	Click []string `json:"click"`
	Exposure []string `json:"exposure"`
}

//ssp_traffic
//"{\"midroll_strategies\": \"\", \"downstreams\": [{\"url\": \"http://testlecloud.com:8000/cld?\",
//\"30_percentage\": 50, \"15_percentage\": 50, \"percentage\": 100, \"type\": 0, \"id\": 6}], 
// \"targeting_units\": [{\"value_id\": 995, \"targeting_type\": 6, \"is_positive\": true}, 
// {\"value_id\": 993, \"targeting_type\": 6, \"is_positive\": true}, {\"value_id\": 991, 
// \"targeting_type\": 6, \"is_positive\": true}, {\"value_id\": 989, \"targeting_type\": 6, 
// \"is_positive\": true}, {\"value_id\": 1156000000, \"targeting_type\": 1, \"is_positive\": true}], 
// \"times\": [{\"start_time\": 1487001600, \"end_time\": 1798819199}], \"preroll_strategies\": \"60,3600,60,45\",
//  \"postroll_strategies\": \"\", \"type\": 2}"


func getMulValueFromMysql(stmtStr string, id int) map[int]map[string]string {

	db, err := sql.Open("mysql", dsn)

	if err != nil {
		fmt.Println(err)
		return nil
	}

	defer db.Close()

	//stmt, err1 := db.Prepare("select advertiser_id from blockrule_advertiser where blockrule_id = ?")
	stmt, err1 := db.Prepare(stmtStr)

	if err1 != nil {
		fmt.Println(err1)
		return nil
	}

	defer stmt.Close()

	results := make(map[int]map[string]string)

	if stmt != nil {
		rows, _ := stmt.Query(id)

		column, _ := rows.Columns()
		values := make([][]byte, len(column))
		scans := make([]interface{}, len(column))

		for i := range values {
			scans[i] = &values[i]
		}

		i := 0
		for rows.Next() {
			if err := rows.Scan(scans...); err != nil {
				fmt.Println(err)
				return nil
			}

			row := make(map[string]string)

			for k, v := range values {
				key := column[k]
				row[key] = string(v)
			}
			results[i] = row
			i++
		}	
	}

    // for k, v := range results { //查询出来的数组  
    //         fmt.Println("mysql :", k , v)  
    // } 
    // fmt.Println(len(results))
    // fmt.Println(len(results[0]))
	return results

}

func getPrerollStrategiesFromMysql(id int) string {

	mysqlValue1 := getMulValueFromMysql("select id, total_duration from cuepoint where delete_flag = 0 and basic_policy_id = ?", id)

	var tempId int
	var prerollStrategies string

	for i := 0; i < len(mysqlValue1); i++ {
		tempId, _= strconv.Atoi(mysqlValue1[i]["id"])

		mysqlValue2 := getMulValueFromMysql("select pre_cue_point_id from cue_prepoints where cuepoint_id = ?", tempId)

		if len(mysqlValue2) < 1 {
			return ""
		}

		tempId, _ = strconv.Atoi(mysqlValue2[i]["pre_cue_point_id"])

		mysqlValue3 := getMulValueFromMysql("select max_limit, min_limit, duration from pre_cuepoint where id =  ?", tempId)

		fmt.Println(mysqlValue3[i]["min_limit"] + "," + mysqlValue3[i]["max_limit"] + "," + mysqlValue3[i]["duration"] + "," + mysqlValue1[i]["total_duration"])
		if i == 0 {
			prerollStrategies = prerollStrategies + mysqlValue3[i]["min_limit"] + "," + mysqlValue3[i]["max_limit"] + "," + mysqlValue3[i]["duration"] + "," + mysqlValue1[i]["total_duration"]

		} else {
			prerollStrategies = prerollStrategies + ";" + mysqlValue3[i]["min_limit"] + "," + mysqlValue3[i]["max_limit"] + "," + mysqlValue3[i]["duration"] + "," + mysqlValue1[i]["total_duration"]

		}
	}
	return prerollStrategies
} 

func getPostrollStrategiesFromMysql(id int) string {
	mysqlValue := getMulValueFromMysql("select total_duration from cuepoint where delete_flag = 0 and basic_policy_id = ?", id) 
	return mysqlValue[0]["total_duration"]
}	

func getMidrollStrategiesFromMysql(id, adzoneType int) string {
	mysqlValue := getMulValueFromMysql("select begin_time, time_type, total_duration from mid_cuepoint where delete_flag = 0 and basic_policy_id = ?", id)

	var midroll string
	var midrollResult string
	for i := 0; i < len(mysqlValue); i++ {
		midroll = mysqlValue[i]["begin_time"] + "," + mysqlValue[i]["time_type"]

		if adzoneType == 4 {
			midroll = midroll + ",1," + mysqlValue[i]["total_duration"]
		} else {
			midroll = midroll + ",2," + mysqlValue[i]["total_duration"]
		}
		midrollResult = midrollResult + ";" + midroll
	}
	return midrollResult
}

func getDownstreamsFromMysql(id int) map[int]map[string]string {
	
	downstreamsResults := make(map[int]map[string]string)
	var adServerId int 
	var returnAdId int

	mysqlValue := getMulValueFromMysql("select ad_server_id, return_ad_server_id, proportion,fifteen_proportion,thirty_proportion ,min_flush_num,max_flush_num,flush_direction from traffic_divide where delete_flag = 0 and basic_policy_id = ?", id)

	for k, _ := range mysqlValue {
		downstreamsResults[k] = make(map[string]string)
		downstreamsResults[k]["percentage"] = mysqlValue[k]["proportion"]
		downstreamsResults[k]["15_percentage"] = mysqlValue[k]["fifteen_proportion"]
		downstreamsResults[k]["30_percentage"] = mysqlValue[k]["thirty_proportion"]
		downstreamsResults[k]["id"] = mysqlValue[k]["ad_server_id"]
		downstreamsResults[k]["type"] = "0"
		
		downstreamsResults[k]["flush_direction"] = mysqlValue[k]["flush_direction"]

		if (mysqlValue[k]["min_flush_num"] == "") {
			downstreamsResults[k]["flush_count"] = ""
		} else {
			downstreamsResults[k]["flush_count"] = mysqlValue[k]["min_flush_num"] + "," + mysqlValue[k]["max_flush_num"]
		}

		adServerId, _ = strconv.Atoi(mysqlValue[k]["ad_server_id"])

		if adServerId == 3 {
			downstreamsResults[k]["type"] = "1"
		}

		returnAdId, _ = strconv.Atoi(mysqlValue[k]["return_ad_server_id"])

		if returnAdId > 0 {
			mysqlValue2 := getMulValueFromMysql("select url from ad_server where delete_flag = 0 and id = ?", returnAdId)

			downstreamsResults[k]["traffic_reuse_url"] = mysqlValue2[0]["url"]
			downstreamsResults[k]["traffic_reuse_id"] = mysqlValue[k]["return_ad_server_id"]
		}

		mysqlValue1 := getMulValueFromMysql("select url from ad_server where delete_flag = 0 and id = ?", adServerId)

		
		downstreamsResults[k]["url"] = mysqlValue1[0]["url"]

	}

	return downstreamsResults
}

func getOneValueFromMysql(stmtStr string, id int) []int {

	db, err := sql.Open("mysql",dsn)

	if err != nil {
		fmt.Println(err)
		return nil
	}

	defer db.Close()

	//stmt, err1 := db.Prepare("select advertiser_id from blockrule_advertiser where blockrule_id = ?")
	stmt, err1 := db.Prepare(stmtStr)

	if err1 != nil {
		fmt.Println(err1)
		return nil
	}

	defer stmt.Close()

	var value int
	var results []int

	if stmt != nil {
		rows, _ := stmt.Query(id)

		for rows.Next() {
			if err := rows.Scan(&value); err != nil {
				fmt.Println(err)
				return nil
			}
			results = append(results, value)

		}	
	}

	return results
}

// func compareTwoSlice(m,n  []interface{} ) (b bool, err error) {

// 	if len(m) == len(n) {
// 		for j := 0; j < len(m); j++ {
// 			switch m[j].(type){
// 			case string:
// 			case int:
// 				if m[j] == n[j] {

// 				} else {
// 					return false, errors.New("the two slice value error")
// 				}
// 			default:
// 				return false, errors.New("unsuppored type")
// 			}
// 		}
// 		return true, nil
// 	} else {
// 		return false, errors.New("the two slice lenght error") 
// 	}
// }

func clearMap(m map[int]map[string]string) {
	for k, _ := range m {
		delete(m,k)
	}
}

func compareTwoSlice(m,n  []int ) (b bool, err error) {

	if len(m) == len(n) {
		for j := 0; j < len(m); j++ {
			if m[j] == n[j] {

			} else {
				return false, errors.New("the two slice value error")
			}
		}
		return true, nil
	} else {
		return false, errors.New("the two slice lenght error") 
	}
}

func verifyAdzone() {
	adzoneKeys, err := redisClient.Keys("adzone.[12346789]*")

	if err != nil {
		fmt.Println("get adzone keys error")
		return
	}

	var redisAdzoneValue adzone
	var id []string
	var idi int


	for i := 0; i < len(adzoneKeys); i++ {
		
		//redis
		rvalue, _ := redisClient.Get(adzoneKeys[i])

		json.Unmarshal(rvalue, &redisAdzoneValue)

		fmt.Println("redis : " + adzoneKeys[i] + " : " + string(rvalue))

		// fmt.Println(redisAdzoneValue.MediaId)
		// fmt.Println(redisAdzoneValue.BusinessLine)
		// fmt.Println(redisAdzoneValue.RollType)
		// fmt.Println(redisAdzoneValue.Width)
		// fmt.Println(redisAdzoneValue.Height)
		
		// fmt.Println(redisAdzoneValue.PublisherId)
		// fmt.Println(redisAdzoneValue.Click)
		// fmt.Println(redisAdzoneValue.Exposure)

		//mysql
		id = strings.Split(adzoneKeys[i],".")
		idi,_ = strconv.Atoi(id[1])

		valueMysql := getMulValueFromMysql("select media_id, biz_id, roll_type, width, height from adzone where id = ?", idi)

		//when height and width is null in mysql, the value is zero in redis
		if valueMysql[0]["width"] == "" {
			valueMysql[0]["width"] = "0"
		}

		if valueMysql[0]["height"] == "" {
			valueMysql[0]["height"] = "0"
		}

		mediaId, _ :=  strconv.Atoi(valueMysql[0]["media_id"])

		publisherId := getOneValueFromMysql("select b.publisher_id from adzone a,media b where b.id = ?", mediaId)

		
		if strings.EqualFold(strconv.Itoa(redisAdzoneValue.MediaId), valueMysql[0]["media_id"]) &&
		strings.EqualFold(strconv.Itoa(redisAdzoneValue.BusinessLine), valueMysql[0]["biz_id"]) &&
		strings.EqualFold(strconv.Itoa(redisAdzoneValue.RollType), valueMysql[0]["roll_type"]) &&
		strings.EqualFold(strconv.Itoa(redisAdzoneValue.Width), valueMysql[0]["width"]) &&
		strings.EqualFold(strconv.Itoa(redisAdzoneValue.Height), valueMysql[0]["height"]) &&
		redisAdzoneValue.PublisherId == publisherId[0] {
			fmt.Println(adzoneKeys[i] + " verify PASSED")
		} else {
			fmt.Println(adzoneKeys[i] + " verify FAILED")
			fmt.Println("mysql : media_id : ",  valueMysql[0]["media_id"])
			fmt.Println("mysql : height : ", valueMysql[0]["height"])
			fmt.Println("mysql : width : ",  valueMysql[0]["width"])
			fmt.Println("mysql : business_line : ",  valueMysql[0]["biz_id"])
			fmt.Println("mysql : roll_type : ",  valueMysql[0]["roll_type"])
			fmt.Println("mysql : publiser id : ",  publisherId[0])
		}
	}
}

func verifyBusinessLine() {
	businessLineKeys, err := redisClient.Keys("business_line.*")

	if err != nil{
		fmt.Println("get business_line keys error")
		return
	}

	var id []string
	var idi int

	var redisBusinessLineValue businessLine

	for i := 0; i < len(businessLineKeys); i++ {

		//redis
		rvalue, _ := redisClient.Get(businessLineKeys[i])

		json.Unmarshal(rvalue, &redisBusinessLineValue)

		fmt.Println("redis : " + businessLineKeys[i] + " : " + string(rvalue))

		//mysql
		id = strings.Split(businessLineKeys[i], ".")
		
		if len(id) >= 2{
			idi,_ = strconv.Atoi(id[1])
		} else {
			continue
		}
		
		valueMysql := getMulValueFromMysql("select id, app_pkg_name, category_id, platform_id, product_id from biz where id = ?", idi)

		// fmt.Println(redisBusinessLineValue.Category)
		// fmt.Println(redisBusinessLineValue.BundleName)
		// fmt.Println(redisBusinessLineValue.TerminalId)
		// fmt.Println(redisBusinessLineValue.ProductId)

		// fmt.Println(valueMysql[0]["category_id"])
		// fmt.Println(valueMysql[0]["app_pkg_name"])
		// fmt.Println(valueMysql[0]["platform_id"])
		// fmt.Println(valueMysql[0]["product_id"])

		//when product_id is null in mysql, the value is zero in redis
		if valueMysql[0]["product_id"] == "" {
		   valueMysql[0]["product_id"] = "0"
		}

		if strings.EqualFold(strconv.Itoa(redisBusinessLineValue.Category), valueMysql[0]["category_id"]) &&
		   strings.EqualFold(redisBusinessLineValue.BundleName, valueMysql[0]["app_pkg_name"]) &&
		   strings.EqualFold(strconv.Itoa(redisBusinessLineValue.TerminalId), valueMysql[0]["platform_id"]) &&
		   strings.EqualFold(strconv.Itoa(redisBusinessLineValue.ProductId), valueMysql[0]["product_id"]) {

			fmt.Println(businessLineKeys[i] + " verify PASSED")
		} else {
			fmt.Println("mysql : category:",valueMysql[0]["category_id"]," bundle_name:",valueMysql[0]["app_pkg_name"]," terminal_id:",valueMysql[0]["platform_id"]," product_id:",valueMysql[0]["product_id"])
			fmt.Println(businessLineKeys[i] + " verify FAILED")
		}
	}
}

func verifySspTraffic() {
	
	sspTrafficKeys, err := redisClient.Keys("ssp_traffic.*")

	if err != nil {
		fmt.Println("get ssp_traffic keys error")
		return
	}

	var f interface{}
	contentMap := make(map[string]string)
	contentDownstreamsMap := make(map[int](map[string]string))
	contentTargetingUnitsMap := make(map[int](map[string]string))
	contentTimesMap := make(map[int](map[string]string))

	for i := 0; i < len(sspTrafficKeys); i++ {

		//clearMap(contentMap)
		clearMap(contentDownstreamsMap)
		clearMap(contentTargetingUnitsMap)
		clearMap(contentTimesMap)

		//redis
		rvalue, _ := redisClient.Get(sspTrafficKeys[i])

		fmt.Println("redis value :",sspTrafficKeys[i] + " : " + string(rvalue))

		json.Unmarshal(rvalue, &f)

		m := f.(map[string]interface{})

		for k, v := range m {
			switch vv := v.(type) {
			case string:
				//fmt.Println(k, " string " , vv)
				contentMap[k] = vv
			case int:
				//fmt.Println(k, " int ", strconv.Itoa(vv))
				contentMap[k] = strconv.Itoa(vv)
			case float64:
				//fmt.Println(k, " float64  ", vv)
				contentMap[k] = strconv.FormatFloat(vv, 'f', 0, 64)
			case []interface{}:
				//fmt.Println(k, "is an array:")
				if k == "downstreams" {
					for i, u := range vv {
						n := u.(map[string]interface{})
						contentDownstreamsMap[i] = make(map[string]string)
						for k1, v1 := range n {
							switch vv1 := v1.(type) {
							case string:
								//fmt.Println(k1, vv1)
								contentDownstreamsMap[i][k1] = vv1
							case int:
								//fmt.Println(k1, strconv.Itoa(vv1))
								contentDownstreamsMap[i][k1] = strconv.Itoa(vv1)
							case float64:
								//fmt.Println(k1, vv1)
								contentDownstreamsMap[i][k1] = strconv.FormatFloat(vv1, 'f', 0, 64)
							case bool:
								//fmt.Println(k1, vv1)
								//contentDownstreamsMap[i][k1] = strconv.FormatBool(vv1)
								if vv1 {
									contentDownstreamsMap[i][k1] = "1"
								} else {
									contentDownstreamsMap[i][k1] = "0"
								}
							default:
								fmt.Println("unsupported type. FAILED")
								fmt.Println("content", vv1)
							}
						}
					}
				} else if k == "targeting_units" {
					for i, u := range vv {
						n := u.(map[string]interface{})
						contentTargetingUnitsMap[i] = make(map[string]string)
						for k1, v1 := range n {
							switch vv1 := v1.(type) {
							case string:
								//fmt.Println(k1, vv1)
								contentTargetingUnitsMap[i][k1] = vv1
							case int:
								//fmt.Println(k1, strconv.Itoa(vv1))
								contentTargetingUnitsMap[i][k1] = strconv.Itoa(vv1)
							case float64:
								//fmt.Println(k1, vv1)
								contentTargetingUnitsMap[i][k1] = strconv.FormatFloat(vv1, 'f', 0, 64)
							case bool:
								//fmt.Println(k1, vv1)
								//contentTargetingUnitsMap[i][k1] = strconv.FormatBool(vv1)
								if vv1 {
									contentTargetingUnitsMap[i][k1] = "1"
								} else {
									contentTargetingUnitsMap[i][k1] = "0"
								}
							default:
								fmt.Println("unsupported type")
							}
						}
					}
				} else if k == "times" {
					for i, u := range vv {
						n := u.(map[string]interface{})
						contentTimesMap[i] = make(map[string]string)
						for k1, v1 := range n {
							switch vv1 := v1.(type) {
							case string:
								//fmt.Println(k1, vv1)
								contentTimesMap[i][k1] = vv1
							case int:
								//fmt.Println(k1, strconv.Itoa(vv1))
								contentTimesMap[i][k1] = strconv.Itoa(vv1)
							case float64:
								//fmt.Println(k1, vv1)
								contentTimesMap[i][k1] = strconv.FormatFloat(vv1, 'f', 0, 64)
							case bool:
								//fmt.Println(k1, vv1)
								//contentTimesMap[i][k1] = strconv.FormatBool(vv1)
								if vv1 {
									contentTimesMap[i][k1] = "1"
								} else {
									contentTimesMap[i][k1] = "0"
								}
							default:
								fmt.Println("unsupported type")
							}
						}
					}
				}


			default:
				fmt.Println(k, "is of a type I don't know how to handle")
			}
		}

		fmt.Println("content")
		// for k, v := range contentMap {
		// 	fmt.Println(k, " : ",v)
		// }

		id := strings.Split(sspTrafficKeys[i],".")
		idi, _:= strconv.Atoi(id[1])


		//content 
		//type  : select type from basic_policy where id = ?;

		mysqlValue := getMulValueFromMysql("select adzone_type, type from basic_policy where id = ?", idi)
		adzoneTypeTemp,_ := strconv.Atoi(mysqlValue[0]["adzone_type"])

		if len(mysqlValue) <= 0 {
			fmt.Println("content type verfiy FAILED")
		}

		if strings.EqualFold(contentMap["type"],mysqlValue[0]["type"]) {
			fmt.Println("content type verify PASSED")
		} else {
			fmt.Println("content type verfiy FAILED")
		}

		//preroll_strategies : 
		if adzoneTypeTemp == 2 {
			if strings.EqualFold(contentMap["preroll_strategies"],getPrerollStrategiesFromMysql(idi)) {
				fmt.Println("content preroll_strategies verify PASSED")
			} else {
				fmt.Println("mysql value : ", getPrerollStrategiesFromMysql(idi))
				fmt.Println("content preroll_strategies verify FAILED")
			}
		} else {
			fmt.Println("adzone_type : ", adzoneTypeTemp, "preroll_strategies is not nesscery to verify")
		}

		//postroll_strategies
		if adzoneTypeTemp == 5 {
			if strings.EqualFold(contentMap["postroll_strategies"],getPostrollStrategiesFromMysql(idi)) {
				fmt.Println("content postroll_strategies verify PASSED")
			} else {
				fmt.Println("mysql value : ",getPostrollStrategiesFromMysql(idi))
				fmt.Println("content postroll_strategies verify FAILED")
			}
		}	else {
			fmt.Println("adzone_type : ", adzoneTypeTemp, "postroll_strategies is not nesscery to verify")
		}
		//midroll_strategies
		if adzoneTypeTemp == 2 && adzoneTypeTemp == 7 {
			if strings.EqualFold(contentMap["midroll_strategies"],getMidrollStrategiesFromMysql(idi, adzoneTypeTemp)) {
				fmt.Println("content midroll_strategies verify PASSED")
			} else {
				fmt.Println("mysql value : ",getMidrollStrategiesFromMysql(idi, adzoneTypeTemp))
				fmt.Println("content midroll_strategies verify FAILED")
			}
		} else {
			fmt.Println("adzone_type : ", adzoneTypeTemp, "midroll_strategies is not nesscery to verify")
		}

		// select id, adzone_type, start_date, end_date, type from basic_policy where delete_flag = 0 and valid_status = 1

		// targeting_units
		// select policy_target_type, value_id, is_positive+0 from policy_target where delete_flag = 0 and basic_policy_id = %d

		targetingUnitsMysqlValue := getMulValueFromMysql("select policy_target_type, value_id, is_positive+0 from policy_target where delete_flag = 0 and basic_policy_id = ?", idi)
		
		fmt.Println("target_untis")

		// for k, _ := range contentTargetingUnitsMap {
		// 	for k1, v1 := range contentTargetingUnitsMap[k] {
		// 		fmt.Println(k1, " : ", v1)
		// 	}
		// }

		//fmt.Println(len(contentTargetingUnitsMap), ",", len(targetingUnitsMysqlValue))
		if len(contentTargetingUnitsMap) == len(targetingUnitsMysqlValue) {
			for k, _ := range contentTargetingUnitsMap {

				if strings.EqualFold(contentTargetingUnitsMap[k]["value_id"],targetingUnitsMysqlValue[k]["value_id"]) &&
				strings.EqualFold(contentTargetingUnitsMap[k]["is_positive"],targetingUnitsMysqlValue[k]["is_positive+0"]) &&
				strings.EqualFold(contentTargetingUnitsMap[k]["targeting_type"],targetingUnitsMysqlValue[k]["policy_target_type"]) {
					fmt.Println("verify target Untials PASSED")
				} else {
					fmt.Println("verify target Untils value FAILED")
				}
			}
		} else {
			fmt.Println("verify target Untils length FAILED")
		}

		// downstreams
		// select ad_server_id, return_ad_server_id, proportion,fifteen_proportion,thirty_proportion from traffic_divide where delete_flag = 0 and basic_policy_id = %d

		fmt.Println("downstreams")
		// for k, _ := range contentDownstreamsMap {
		// 	for k1, v1 := range contentDownstreamsMap[k] {
		// 		fmt.Println(k1, " : ", v1)
		// 	}
		// }

		downstreamsMysqlValue := getDownstreamsFromMysql(idi)

		if len(contentDownstreamsMap) == len(downstreamsMysqlValue) {
			for k, _ := range contentDownstreamsMap {
				if strings.EqualFold(contentDownstreamsMap[k]["id"],downstreamsMysqlValue[k]["id"]) &&
				strings.EqualFold(contentDownstreamsMap[k]["url"],downstreamsMysqlValue[k]["url"]) &&
				strings.EqualFold(contentDownstreamsMap[k]["type"],downstreamsMysqlValue[k]["type"]) &&
				strings.EqualFold(contentDownstreamsMap[k]["percentage"],downstreamsMysqlValue[k]["percentage"]) &&
				strings.EqualFold(contentDownstreamsMap[k]["15_percentage"],downstreamsMysqlValue[k]["15_percentage"]) &&
				strings.EqualFold(contentDownstreamsMap[k]["30_percentage"],downstreamsMysqlValue[k]["30_percentage"]) &&
				strings.EqualFold(contentDownstreamsMap[k]["traffic_reuse_url"],downstreamsMysqlValue[k]["traffic_reuse_url"]) &&
				strings.EqualFold(contentDownstreamsMap[k]["traffic_reuse_id"],downstreamsMysqlValue[k]["traffic_reuse_id"]) && 
				strings.EqualFold(contentDownstreamsMap[k]["flush_count"],downstreamsMysqlValue[k]["flush_count"]) &&
				strings.EqualFold(contentDownstreamsMap[k]["flush_direction"],downstreamsMysqlValue[k]["flush_direction"]){
					fmt.Println("verify downstreams PASSED")
				} else {
					fmt.Println("verify downstreams value FAILED")
					fmt.Println("mysql value:")
					fmt.Println("id = " + downstreamsMysqlValue[k]["id"])
					fmt.Println("url = " + downstreamsMysqlValue[k]["url"])
					fmt.Println("type = " + downstreamsMysqlValue[k]["type"])
					fmt.Println("percentage = " + downstreamsMysqlValue[k]["percentage"])
					fmt.Println("15_percentage = " + downstreamsMysqlValue[k]["15_percentage"])
					fmt.Println("30_percentage = " + downstreamsMysqlValue[k]["30_percentage"])
					fmt.Println("traffic_reuse_url = " + downstreamsMysqlValue[k]["traffic_reuse_url"])
					fmt.Println("traffic_reuse_id = "  + downstreamsMysqlValue[k]["traffic_reuse_id"])
					fmt.Println("flush_count = "  + downstreamsMysqlValue[k]["flush_count"])
					fmt.Println("flush_direction = "  + downstreamsMysqlValue[k]["flush_direction"])
				}
			}
		} else {
			fmt.Println("verify downstreams length FAILED")
		}

				
		//times

		fmt.Println("don't verify times now")
		// for k, _ := range contentTimesMap {
		// 	for k1, v1 := range contentTimesMap[k] {
		// 		fmt.Println(k1, " : ", v1)
		// 	}
		// }
	}

}

var materialTypeMap = map[int]string{0:"image/jpeg", 1:"image/png", 3:"application/x-shockwave-flash", 4:"video/x-flv", 5:"video/mp4", 6:"image/gif", 7:"application/letv-vpaid"}

func verfiyAdzoneMaterialType() {
	adzoneMaterialTypeKeys, err := redisClient.Keys("adzone_material_type*")

	if err != nil {
		fmt.Println("get adzone_material_type keys error")
		return
	}

	var id []string
	var idi int
	var isPassed bool

	for i := 0; i < len(adzoneMaterialTypeKeys); i++ {
		rvalue,_ := redisClient.Smembers(adzoneMaterialTypeKeys[i])

		id = strings.Split(adzoneMaterialTypeKeys[i],".")
		idi,_ = strconv.Atoi(id[1])

		valueMysql := getOneValueFromMysql("select ad_type from adzone_ad_types where adzone_id = ?",idi)
		if len(rvalue) == len(valueMysql) {
			for j := 0; j < len(valueMysql); j++ {
				isPassed = false
				for _, v := range rvalue {
					//fmt.Println(k, string(v))
					if strings.EqualFold(materialTypeMap[valueMysql[j]],string(v)) {
						isPassed = true
						break
					}
				}

				if !isPassed {
					break
				}
			}
		}	else {
			fmt.Println("verify ", adzoneMaterialTypeKeys[i], "length FAILED")
			continue
		}

		if isPassed {
			fmt.Println("verify ", adzoneMaterialTypeKeys[i], " PASSED")
		} else {
			fmt.Println("verify ", adzoneMaterialTypeKeys[i], " FAILED")
		}
	}
}

func verifyBlockrule() {

	blockruleKeys, err := redisClient.Keys("blockrule.[123456789]*")

	if err != nil {
		fmt.Println("get blockrule keys error")
		return
	}

	var redisBlockRuleValue blockRule

	var id []string
	var valueMysql []int
	var idi int

	for i := 0; i < len(blockruleKeys); i++ {

		// redis
		rvalue, _ := redisClient.Get(blockruleKeys[i])

		json.Unmarshal(rvalue, &redisBlockRuleValue)

		fmt.Println(blockruleKeys[i] + ":" + string(rvalue))

		// fmt.Println(redisBlockRuleValue.Advertiser)
		// fmt.Println(redisBlockRuleValue.Areaid)
		// fmt.Println(redisBlockRuleValue.Cid)
		// fmt.Println(redisBlockRuleValue.Sspid)
		// fmt.Println(redisBlockRuleValue.Industry)
		// fmt.Println(redisBlockRuleValue.Pid)
		// fmt.Println(redisBlockRuleValue.BusinessId)

		//mysql
		id = strings.Split(blockruleKeys[i], ".")
		if len(id) >= 2 {
			idi,_ = strconv.Atoi(id[1])
		} else {
			continue
		}

		valueMysql = getOneValueFromMysql("select advertiser_id from blockrule_advertiser where blockrule_id = ?",idi) 

		ok, _ := compareTwoSlice(valueMysql, redisBlockRuleValue.Advertiser)
		if ok{
			fmt.Println("the table blockrule's advertiser equel. PASSED")
		} else {
			fmt.Println("the table blockrule's advertiser not equel. FAILED")
		}

		valueMysql = getOneValueFromMysql("select area_id from blockrule_area where blockrule_id = ?",idi)

		ok, _ = compareTwoSlice(valueMysql, redisBlockRuleValue.Areaid)
		if ok{
			fmt.Println("the table blockrule's Areaid equel. PASSED")
		} else {
			fmt.Println("the table blockrule's Areaid not equel. FAILED")
		}

		valueMysql = getOneValueFromMysql("select media_id from blockrule_media where blockrule_id = ?",idi)

		ok, _ = compareTwoSlice(valueMysql, redisBlockRuleValue.Sspid)
		if ok{
			fmt.Println("the table blockrule's Sspid equel. PASSED")
		} else {
			fmt.Println("the table blockrule's Sspid not equel. FAILED")
		}

		valueMysql = getOneValueFromMysql("select industry_id from blockrule_industry where blockrule_id = ?",idi)
		
		ok, _ = compareTwoSlice(valueMysql, redisBlockRuleValue.Industry)
		if ok{
			fmt.Println("the table blockrule's Industry equel. PASSED")
		} else {
			fmt.Println("the table blockrule's Industry not equel. FAILED")
		}
	}
}

type config struct {
	Master_redis_ip	string	`yaml:"master-redis-ip"`
	Master_redis_port	string `yaml:"master-redis-port"`
	Master_redis_password	string	`yaml:"master-redis-password"`
	Mysql_ip	string `yaml:"mysql-ip"`
	Mysql_port	string `yaml:"mysql-port"`
	Mysql_username	string	`yaml:"mysql-username"`
	Mysql_password	string	`yaml:"mysql-password"`
	Mysql_db	string `yaml:"mysql-db"`
}

var redisClient redis.Client
var dsn string

func loadConfig(file string) {

	buf, err := ioutil.ReadFile(file)

	if err != nil {
		fmt.Println("load config FAILED")
		return
	}
	var configp config

	err = yaml.Unmarshal(buf, &configp)

	if err != nil {
		fmt.Println("yaml unmarshal FAILED")
		return
	}

	redisClient.Addr = configp.Master_redis_ip + ":" + configp.Master_redis_port
	redisClient.Password = configp.Master_redis_password

	//root:root@tcp(127.0.0.1:3306)/ssp_online_test?charset=utf8
	dsn = configp.Mysql_username + ":" + configp.Mysql_password + "@tcp(" + configp.Mysql_ip + ":" + configp.Mysql_port + ")/" + configp.Mysql_db + "?charset=utf8"

}

func main () {

	//redisClient.Addr = "127.0.0.1:6379"
	loadConfig("./config/config.yaml")
	
	// verifyBlockrule()
	// verifyBusinessLine()
	// verifyAdzone()
	 verifySspTraffic()
	// verfiyAdzoneMaterialType()
}
